package myJs.user.workflowMission.featureSelectionResult

import myJs.Implicits._
import myJs.Utils._
import myJs.api.Api
import myJs.myPkg._
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.myPkg.jquery._
import myJs.myPkg.topology._
import myJs.tool.Tool
import myJs.tool.Tool._
import myJs.user.FeatureSelectionTool
import myJs.user.workflow.featureSelection.diagnoseAna.DiagnoseAna
import myJs.user.workflow.featureSelection.pathwayAna.PathwayAna
import myJs.user.workflow.featureSelection.pca.Pca
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.{Element, document, window}
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import scalatags.Text.all._
import scalax.collection.GraphTraversal.BreadthFirst

import scala.collection.immutable.SeqMap
import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}


/**
 * Created by yz on 2019/4/25
 */
@JSExportTopLevel("FeatureSelectionResult")
object FeatureSelectionResult extends FeatureSelectionTool {

  val formId = "form"
  var topology: Topology = _
  val tableId = "table"
  val modalId = "viewModal"
  var selectedPen: Pen = _
  val lastSofts = List(PathwayAna, DiagnoseAna,Pca)

  @JSExport("init")
  def init = {
    refreshMissionInfo(getMissionId)

    registerEvent

    {
      import cats.effect.unsafe.implicits.global
      Api.workflowMission.configData(Tool.getMissionId).map { curFsData =>
        Cp.Props(fsData = curFsData).render.renderIntoDOM(document.querySelector("#args"))
      }.unsafeRunAndForget()
    }



    val leftResizeOptions = ResizableOptions.resizeWidth(true).resizeHeight(false).
      handleSelector(".leftHandler,.leftDrag").
      onDrag(leftDrag).resizeWidthFrom("right")
    $("#left").resizable(leftResizeOptions)

    Tool.rightResizable

  }

  def myCopyJq = {
    $(":input[name='myCopy']")
  }

  def getDiffNum(ids: js.Array[String]) = {
    val url = g.jsRoutes.controllers.WorkflowController.getDiffNum().url.toString
    val dict = js.Dictionary("idStrs" -> ids, "missionId" -> getMissionId)
    val data = JSON.stringify(dict)
    Ajax.post(url = s"${url}", data = data, headers = Map("Content-Type" -> "application/json")).map { xhr =>
      xhr.responseText.toJDI
    }
  }

  def refreshResult(idStr: String) = {
    val curSoft = getCurSoft(idStr)
    $(".result").hide()
    curSoft.refreshResult(idStr)
  }

  def getMissionId = {
    g.missionId.toString
  }

  def registerEvent = {
    $(document.body).on("click", ".myToggle", "", (y: Element) => {
      val tabJq = $(y).parents(".tab-pane")
      Tool.myToggle(tabJq)
    })

    $(document.body).on("click", ".myViewFile", "", (y: Element) => {
      val fileName = $(y).dataValue
      viewFile(fileName)
    })
    $(s"#${modalId}").on("shown.bs.modal", () => {
      val fileName = getFileName
      refreshData(fileName)
    })
    $(document.body).on("click", ".myCopy", "", (y: Element) => {
      myCopyJq.show()
      myCopyJq.select()
      document.execCommand("Copy")
      myCopyJq.hide()
      window.alert(messages("copySuccessfully"))
    })
  }

  def getFileName = {
    val fileNameJq = $(s"#${modalId} #fileName")
    val trueFileName = fileNameJq.text().trim
    val relPath = fileNameJq.dataValue
    List(relPath, trueFileName).notEmptyLines.mkString("/")
  }

  def selectPen(topology: Topology, pen: Pen) = {
    addPen2ActiveLayer(topology, pen)
    $(".nodeText").attr("id", pen.id)
    refreshFileInfo(pen.id).zip(refreshDiffMetabolite).map { x =>
      $(".nodeText").text(pen.toNode.text.replaceAll("\\(.*$", ""))
    }
    refreshResult(pen.id)
  }

  def refreshGroups(idStr: String) = {
    val url = g.jsRoutes.controllers.MissionToolController.getGroups().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(s"${url.noCache}&missionId=${Tool.getMissionId}&idStr=${idStr}").
      async(false).`type`("get").headers(js.Dictionary("Content-Type" -> "application/json")).
      success { (data: js.Any, status: String, e: JQueryXHR) =>
        FeatureSelectionTool.groups = data.asInstanceOf[js.Array[String]].toList
      }
    $.ajax(ajaxSettings)
  }

  def refreshRowNames(idStr: String) = {
    val url = g.jsRoutes.controllers.MissionToolController.getRowCols().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(s"${url.noCache}&missionId=${Tool.getMissionId}&idStr=${idStr}").
      async(false).`type`("get").headers(js.Dictionary("Content-Type" -> "application/json")).
      success { (data: js.Any, status: String, e: JQueryXHR) =>
        val rs = data.toJDJAn
        val vs = rs("rowNames").toJArS
        FeatureSelectionTool.rowNames = vs.toList
      }
    $.ajax(ajaxSettings)
  }

  def refreshGroupHeaders(idStr: String) = {
    val url = g.jsRoutes.controllers.MissionToolController.getNumericColNames().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(s"${url.noCache}&missionId=${Tool.getMissionId}&idStr=${idStr}").
      async(false).`type`("get").headers(js.Dictionary("Content-Type" -> "application/json")).
      success { (data: js.Any, status: String, e: JQueryXHR) =>
        val rs = data.toJDJAn
        val headers = rs("headers").toJArS.filterNot { x =>
          List("Sample", "ClassNote", "Pair_ID").contains(x)
        }
        FeatureSelectionTool.groupHeaders = headers.toList
      }
    $.ajax(ajaxSettings)
  }

  def viewFile(fileName: String) = {
    val fileNameJq = $(s"#${modalId} #fileName")
    val names = fileName.split("/")
    val relPath = names.init.mkString("/")
    val trueFileName = names.last
    fileNameJq.dataValue(relPath).text(trueFileName)
    $(s"#${modalId}").modal("show")
  }

  def expFmt(columnName: String, firstName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case x if x == firstName =>
      val json = v.asInstanceOf[js.Dictionary[js.Any]]
      val str = json.myGet("value")
      span(
        str
      )
    case otherName =>
      val json = v.asInstanceOf[js.Dictionary[js.Any]]
      val html = cellView(json, row)
      html
  }

  def cellView(json: js.Dictionary[js.Any], row: js.Dictionary[js.Any]) = {
    val color = json.myGet("color")
    val v = json.myGet("value")
    val bgColor = if (color.nonBlank) {
      s"#${color.drop(2)}"
    } else {
      "white"
    }
    div(width := "100%",
      height := 40,
      backgroundColor := bgColor,
      div(
        paddingLeft := 8,
        paddingRight := 8,
        paddingTop := 10,
        paddingBottom := 10,
        v
      )
    )
  }

  def expStyle(columnName: String, firstName: String): js.Function = (v: js.Any, row: js.Dictionary[Any]) => columnName match {
    case x if x == firstName =>
      js.Dictionary()
    case _ => js.Dictionary("css" -> js.Dictionary(
      "padding" -> 0
    ))
  }

  def refreshData(fileName: String) = {
    val idStr = getIdStr
    val finalFileName = s"${idStr}/${fileName}"
    val index = layer.load(1, Tool.layerOptions.shade(js.Array("0.1", "#fff")))
    val url = g.jsRoutes.controllers.WorkflowController.getFileData().url.toString
    Ajax.get(url = s"${url.noCache}&missionId=${getMissionId}&fileName=${finalFileName}",
      headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val columnNames = rs("columnNames").asInstanceOf[js.Array[String]]
      val columns = columnNames.zipWithIndex.map { case (columnName, index) =>
        fileName.fileNameSuffix match {
          case "xlsx" =>
            val fmt = expFmt(columnName, columnNames.head)
            val style = expStyle(columnName, columnNames.head)
            ColumnOptions.field(index.toString).title(columnName).sortable(true).cellStyle(style).formatter(fmt)
          case _ =>
            val fmt = columnName
            ColumnOptions.field(index.toString).title(columnName).sortable(true)
        }
      }
      val options = TableOptions.data(rs("array")).columns(columns).pagination(true).
        pageList(js.Array("10", "25", "50", "100", "all")).fixedColumns(true).fixedNumber(1).locale(Tool.getBTLanguage)
      $(s"#${modalId} #${tableId}").bootstrapTable("destroy").bootstrapTable(options)
      layer.close(index)
    }
  }

  lazy val operateColumn = js.Array(
    ColumnOptions.field("operate").title(messages("operations")).formatter(operateFmt).filterControl("clear")
  )

  def getIdStr = {
    $(".nodeText").attr("id").getOrElse("")
  }

  def operateFmt: js.Function = {
    (v: js.Any, row: js.Dictionary[js.Any]) =>
      val fileRelPath = if (row.myGet("fileRelPath").strIsBlank) "" else s"${row("fileRelPath")}/"
      val downloadUrl = g.jsRoutes.controllers.WorkflowController.downloadResultFile().url.toString
      val downloadStr = a(title := messages("download"),
        href := s"${downloadUrl}?missionId=${getMissionId}&fileName=${getIdStr}/${fileRelPath}${row("fileName")}",
        cursor.pointer,
        span(em(cls := "fa fa-download"))
      )

      val detailViewStr = a(title := messages("viewDetails"), `class` := "myViewFile",
        dataValue := s"${fileRelPath}${row("fileName")}",
        span(em(cls := "fa fa-eye"))
      )

      val rs = if (List(".pdf", ".zip", ".svg", ".json").exists(x => row("fileName").toString.endsWith(x))) {
        List(downloadStr)
      } else List(detailViewStr, downloadStr)
      rs.mkString("&nbsp;")
  }

  def refreshFileInfo(idStr: String) = {
    val url = g.jsRoutes.controllers.WorkflowController.getFsResultFileInfo().url.toString
    Ajax.get(url = s"${url.noCache}&missionId=${getMissionId}&idStr=${idStr}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val headerMap = SeqMap("fileName" -> messages("file"), "rowNum" -> messages("rowsInDataFile"), "intro" -> messages("note"))
      val columnNames = headerMap.keyList
      val columns = columnNames.map { columnName =>
        val title = headerMap.getOrElse(columnName, columnName)
        ColumnOptions.field(columnName).title(title).sortable(true)
      }.toJSArray.concat(operateColumn)
      val options = TableOptions.data(rs).columns(columns).pagination(false)
      $(s"#resultFile #${tableId}").bootstrapTable("destroy").bootstrapTable(options)
    }
  }

  def refreshDiffMetabolite = {
    val idStr = getIdStr
    val curSoft = getCurSoft(idStr)
    if (lastSofts.contains(curSoft)) {
      Future {
        $("#left .allDiffNum").hide()
        $("#left #table").parents(".table-responsive").hide()
        $("#left #noDiffResult").show()
      }
    } else {
      $("#left .allDiffNum").show()
      $("#left #noDiffResult").hide()
      $("#left #table").parents(".table-responsive").show()
      val fileName = s"Diff_Metabolite.csv"
      refreshLeftData(fileName, tableJq = $("#left #table")).map { x =>
      }
    }
  }

  def refreshLeftData(fileName: String, tableJq: JQuery) = {
    val url = g.jsRoutes.controllers.WorkflowController.getFileData().url.toString
    val idStr = getIdStr
    val finalFileName = s"${idStr}/${fileName}"
    Ajax.get(url = s"${url.noCache}&missionId=${getMissionId}&fileName=${finalFileName}",
      headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDJAn
      val columnNames = rs("columnNames").asInstanceOf[js.Array[String]]
      val columns = columnNames.zipWithIndex.map { case (columnName, index) =>
        val fmt = columnName
        ColumnOptions.field(index.toString).title(columnName).sortable(true)
      }

      val options = TableOptions.data(rs("array")).columns(columns).pagination(true).
        pageList(js.Array("5", "10", "25", "50", "100", "all")).pageSize(5).locale(Tool.getBTLanguage)
      tableJq.bootstrapTable("destroy").bootstrapTable(options)
      val diffDatas = rs("array").toJArJDS
      $("#left .diffNum").text(s"${diffDatas.size}")
      val metaboliteStr = diffDatas.map(_ ("0")).mkString("\n")
      myCopyJq.text(metaboliteStr)
    }
  }


}
